package com.tsfyun.scm.service.impl.order;

import cn.hutool.core.collection.CollUtil;
import com.tsfyun.common.base.enums.BusinessTypeEnum;
import com.tsfyun.common.base.enums.DistributedLockEnum;
import com.tsfyun.common.base.exception.ServiceException;
import com.tsfyun.common.base.util.StringUtils;
import com.tsfyun.common.base.util.TsfPreconditions;
import com.tsfyun.scm.entity.customer.Customer;
import com.tsfyun.scm.entity.finance.ImpSalesContract;
import com.tsfyun.scm.entity.order.ImpOrder;
import com.tsfyun.scm.service.customer.ICustomerService;
import com.tsfyun.scm.service.finance.IImpSalesContractService;
import com.tsfyun.scm.service.order.IImpOrderCostService;
import com.tsfyun.scm.service.order.IImpOrderSalesContractService;
import com.tsfyun.scm.service.order.IImpOrderService;
import com.tsfyun.scm.vo.order.ImpOrderCostVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

/**
 * @Description:
 * @CreateDate: Created in 2020/5/25 14:54
 */
@RefreshScope
@Slf4j
@Service
public class ImpOrderSalesContractServiceImpl implements IImpOrderSalesContractService {

    @Autowired
    private IImpOrderService impOrderService;

    @Autowired
    private ICustomerService customerService;

    @Autowired
    private IImpSalesContractService impSalesContractService;

    @Autowired
    private IImpOrderCostService impOrderCostService;

    @Autowired
    private RedisLockRegistry redisLockRegistry;

    @Value("${redis.lock.time:5}")
    private Integer lockTime;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void generateImpSalesContract(Long orderId, BigDecimal adjustmentAmount) {
        String lockKey = DistributedLockEnum.IMP_ORDER_GENERATE_SALES_CONTRACT.getCode() + ":" + orderId;
        Lock lock = redisLockRegistry.obtain(lockKey);
        boolean isLock;
        try {
            isLock = lock.tryLock(lockTime, TimeUnit.SECONDS);
            if (!isLock) {
                log.error(String.format("生成销售合同未获取到锁，订单id：【%s】", orderId));
                throw new ServiceException("服务拥挤，请稍后再试");
            }

            ImpOrder impOrder = impOrderService.getById(orderId);
            Optional.ofNullable(impOrder).orElseThrow(()->new ServiceException("订单信息不存在"));
            //校验订单客户开票信息
            Customer customer = customerService.getById(impOrder.getCustomerId());
            TsfPreconditions.checkArgument(StringUtils.isNotEmpty(customer.getInvoiceBankName()) && StringUtils.isNotEmpty(customer.getInvoiceBankAccount())
                    && StringUtils.isNotEmpty(customer.getTaxpayerNo()),new ServiceException("客户开票银行信息还未完善，请先完善"));
            TsfPreconditions.checkArgument(Objects.equals(BusinessTypeEnum.IMP_COOPERATE.getCode(),impOrder.getBusinessType()),new ServiceException("请选择自营进口订单操作"));
            TsfPreconditions.checkArgument(Objects.equals(Boolean.TRUE,impOrder.getIsImp()),new ServiceException("确认进口的订单才能操作"));
            //判断订单是否已经生成销售合同
            ImpSalesContract checkImpSalesContract = impSalesContractService.getByOrderNo(impOrder.getDocNo());
            if(Objects.nonNull(checkImpSalesContract)) {
                throw new ServiceException(String.format("订单【%s】已经生成销售合同【%s】",impOrder.getDocNo(),checkImpSalesContract.getDocNo()));
            }
            //获取所有的订单费用信息
            List<ImpOrderCostVO> orderCosts = impOrderCostService.getAllCosts(orderId,null);
            TsfPreconditions.checkArgument(CollUtil.isNotEmpty(orderCosts),new ServiceException(String.format("订单【%s】不存在应收费用信息",impOrder.getDocNo())));
            impSalesContractService.generateByImpOrder(impOrder,orderCosts,customer,adjustmentAmount);
        } catch (InterruptedException e) {
            log.error("自营订单生成销售合同获取锁异常",e);
            throw new ServiceException("服务拥挤，请稍后再试");
        } finally {
            //释放锁
            lock.unlock();
        }
    }

}
